/*
 * TMQL4J - Javabased TMQL Engine
 * 
 * Copyright: Copyright 2010 Topic Maps Lab, University of Leipzig. http://www.topicmapslab.de/    
 * License:   Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.html
 * 
 * @author Sven Krosse
 * @email krosse@informatik.uni-leipzig.de
 *
 */
package de.topicmapslab.tmql4j.components.interpreter;

import java.util.List;

import de.topicmapslab.tmql4j.components.processor.core.IContext;
import de.topicmapslab.tmql4j.components.processor.core.QueryMatches;
import de.topicmapslab.tmql4j.components.processor.runtime.ITMQLRuntime;
import de.topicmapslab.tmql4j.components.processor.runtime.module.InterpreterRegistryImpl;
import de.topicmapslab.tmql4j.exception.TMQLRuntimeException;
import de.topicmapslab.tmql4j.grammar.lexical.IToken;
import de.topicmapslab.tmql4j.grammar.productions.IExpression;

/**
 * Interface definition of the {@link IExpression} interpreters. Every
 * implementation of an {@link IExpression} interpreter is specialized to
 * interpret an instance of {@link IExpression}. During the querying process the
 * generated parser tree containing a tree-structured representation of the
 * query will be interpreted incremental.
 * 
 * <p>
 * An Instance of {@link IExpression} will be an argument of the interpretation
 * process of a {@link IExpressionInterpreter} which will be instantiate by the
 * {@link InterpreterRegistryImpl}.
 * </p>
 * 
 * @author Sven Krosse
 * @email krosse@informatik.uni-leipzig.de
 * 
 * @param <T>
 *            the expression type which specialize the extending interpreter
 *            class
 */
public interface IExpressionInterpreter<T extends IExpression> {

	/**
	 * Method returns the internal reference of the expression which will be
	 * interpreted by this instance.
	 * 
	 * @return the expression which will be interpreted and never
	 *         <code>null</code>.
	 */
	public T getExpression();

	/**
	 * Method called to interpret the current expression.
	 * 
	 * @param runtime
	 *            the runtime
	 * @param context
	 *            the context
	 * @param optionalArguments
	 *            any optional arguments
	 * @return the results of this expression as {@link QueryMatches}
	 * @throws TMQLRuntimeException
	 *             thrown if querying fails
	 */
	public <R extends Object> R interpret(ITMQLRuntime runtime, IContext context, Object... optionalArguments) throws TMQLRuntimeException;

	/**
	 * Method returns a list of all interpreters for the sub-expression of the
	 * internal expression. If the expression is a leaf this method will return
	 * an empty list of interpreters. The method instantiate one interpreter for
	 * each expression by calling the {@link InterpreterRegistryImpl}:
	 * 
	 * @param runtime
	 *            the TMQL4J runtime
	 * @return a list containing all interpreters which are used to interpret
	 *         sub-expressions or an empty list if the expression is a leaf but
	 *         never <code>null</code>.
	 * @throws TMQLRuntimeException
	 *             thrown if at least one instance of
	 *             {@link IExpressionInterpreter} cannot be instantiate.
	 */
	public List<IExpressionInterpreter<?>> getInterpreters(final ITMQLRuntime runtime) throws TMQLRuntimeException;

	/**
	 * Method returns a list of string-represented tokens as a sub-set of the
	 * tokens generated by the lexical scanner. The list of tokens represent the
	 * whole sub-query of the contained production rule ( {@link IExpression} ).
	 * 
	 * @return a list of string-represented tokens
	 */
	public List<String> getTokens();

	/**
	 * Method returns a list of language-specific tokens as a sub-set of the
	 * tokens generated by the lexical scanner. The list of tokens represent the
	 * whole sub-query of the contained production rule ( {@link IExpression} ).
	 * 
	 * @return a list of language-specific tokens
	 */
	public List<Class<? extends IToken>> getTmqlTokens();

	/**
	 * Method checks if the internal expression has at least one child-node of
	 * the given expression type.
	 * <p>
	 * The method is useful because of the fact that some sub-expression are
	 * optional like a where-clause of a select-expression.
	 * </p>
	 * 
	 * @param type
	 *            the type to look for
	 * @return <code>true</code> if the expression has at least one child-node
	 *         of the given type, <code>false</code> otherwise.
	 * @throws TMQLRuntimeException
	 *             thrown if operation fails.
	 */
	public boolean containsExpressionsType(Class<? extends IExpression> type) throws TMQLRuntimeException;

	/**
	 * Method returns a list of all interpreters for the sub-expression of the
	 * internal expression filtered by the given type. If the expression is a
	 * leaf this method will return an empty list of interpreters. The method
	 * instantiate one interpreter for each expression of the given type by
	 * calling the {@link InterpreterRegistryImpl}:
	 * 
	 * @param runtime
	 *            the TMQL4J runtime
	 * @param type
	 *            the filter type
	 * @return a list containing all interpreters which are used to interpret
	 *         sub-expressions filtered by the given type or an empty list if
	 *         the expression is a leaf but never <code>null</code>.
	 * @throws TMQLRuntimeException
	 *             thrown if at least one instance of
	 *             {@link IExpressionInterpreter} cannot be instantiate.
	 */
	public <E extends IExpression> List<IExpressionInterpreter<E>> getInterpretersFilteredByEypressionType(final ITMQLRuntime runtime, Class<E> type) throws TMQLRuntimeException;

	/**
	 * Method extract all language-specific tokens which represents a variable
	 * token and transform them to their string-represented pattern.
	 * 
	 * @return a list of all variables contained in the production rule
	 */
	public List<String> getVariables();

	/**
	 * In the current draft some production rules support different syntactical
	 * patterns and can be differ in grammar levels. The method return an
	 * identifier representing the grammar type at the context of the production
	 * rule.
	 * 
	 * @return a numeric value representing the grammar type
	 */
	public int getGrammarTypeOfExpression();

	/**
	 * The current draft specify a number of different production rules. Each of
	 * this production rules is represented by an instance of
	 * {@link IExpression} and so there are an instance of
	 * {@link IExpressionInterpreter} for each type of {@link IExpression}.
	 * <p>
	 * This method will return the type of the expression which can be handled
	 * by this {@link IExpressionInterpreter} instance.
	 * </p>
	 * 
	 * @return a class object of the supported expression type
	 */
	public Class<T> getTypeOfExpression();

}
